﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using System.Threading;
using CheatMenu.Managers;

namespace CheatMenu.Utils
{
    public static class ScreenshotUtil
    {
        public class ScreenshotTakenResult
        {
            public string SavePath;

            public ScreenshotTakenResult(string savePath)
            {
                SavePath = savePath;
            }
        }
        public delegate void ScreenshotTakenDelegate(ScreenshotTakenResult result);

        public static event ScreenshotTakenDelegate ScreenshotSaved;
        static void OnScreenshotTaken(string savePath)
        {
            ScreenshotSaved?.Invoke(new ScreenshotTakenResult(savePath));
        }

        public static string Path { get; set; } = Application.dataPath;

        public static bool TakeScreenShot(Camera camera = null, float scale = 1f, ImageDataType imageDataType = ImageDataType.PNG)
        {
            bool result = true;
            byte[] imageData = null;
            RenderTexture rTexture = null;
            Texture2D oTexture2D = null;

            Camera rCamera = camera ?? Camera.main;
            Vector2Int rSize = GetScreenSizeFromScalar(scale);

            try
            {
                rTexture = new RenderTexture(rSize.x, rSize.y, 24);
                rCamera.targetTexture = rTexture;
                rCamera.Render();
                rCamera.targetTexture = null;
                RenderTexture.active = rTexture;
                oTexture2D = new Texture2D(rSize.x, rSize.y, TextureFormat.RGB24, false);
                oTexture2D.ReadPixels(new Rect(0, 0, rSize.x, rSize.y), 0, 0);
                RenderTexture.active = null;
                imageData = imageDataType == ImageDataType.JPG ? oTexture2D.EncodeToJPG() : oTexture2D.EncodeToPNG();
            }
            catch(Exception ex)
            {
                LogManager.LogInfo($"[Screenshot] TakeScreenShot Exception: {ex}");
                result = false;
            }
            finally
            {
                if(rTexture != null && rTexture.IsCreated())
                    rTexture.Release();
                if(oTexture2D != null)
                    UnityEngine.Object.Destroy(oTexture2D);
            }

            if (result)
            {
                Thread thread = new Thread(StartWriteThread);
                thread.Start(new ThreadStartData(rSize, imageData, imageDataType));
            }

            return result;
        }

        public static Vector2Int GetScreenSizeFromScalar(float scale)
        => new Vector2Int((int)(Screen.width * scale), (int)(Screen.height * scale));

        private static void StartWriteThread(object state)
        {
            if (state is ThreadStartData data)
            {
                string filename = string.Format("{0}/ss_{1}x{2}_{3}.{4}", Path, data.Size.x, data.Size.y, DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"), data.ImageDataType == ImageDataType.JPG ? "jpg" : "png");
                System.IO.File.WriteAllBytes(filename, data.ImageData);
                LogManager.LogInfo($"Saved Screenshot: {filename}");
                OnScreenshotTaken(filename);
            }
        }
    }

    public enum ImageDataType
    {
        JPG,
        PNG,
    }

    class ThreadStartData
    {
        public Vector2Int Size;
        public byte[] ImageData;
        public ImageDataType ImageDataType;

        public ThreadStartData(Vector2Int size, byte[] data, ImageDataType imageDataType)
        {
            Size = size;
            ImageData = data;
            ImageDataType = imageDataType;
        }
    }
}
